require 'yaml'
require 'fileutils'
CCB = "/ccb"
TMP_RESULT_ROOT = ENV['TMP_RESULT_ROOT'] || '/tmp/lkp/result/'
ENV['OAUTH_TOKEN_URL'] = 'https://omapi.osinfra.cn/oneid/oidc/token'
ENV['OAUTH_REDIRECT_URL'] = 'http://123.249.10.3:30108/oauth/'
ENV['PUBLIC_KEY_URL'] = 'https://omapi.osinfra.cn/oneid/public/key?community=openeuler'

def clone_ccb
  %x(git clone https://gitee.com/duan_pj/ccb.git #{CCB})
  exit(99) unless File.exist?("#{CCB}/sbin/cli/ccb")
  ENV['CCB_SRC'] = CCB
end

def write_cli_config
  data = {
    "GATEWAY_PORT" => 443,
    "GATEWAY_IP" => "eulermaker.compass-ci.openeuler.openatom.cn",
    "SRV_URL" => "https://eulermaker.compass-ci.openeuler.openatom.cn"
  }

  default = "#{ENV['HOME']}/.config/cli/defaults/"
  yp = File.join(default, 'config.yaml')
  FileUtils.mkdir_p(default) unless File.directory?(default)

  File.open(yp, 'w') do |file|
    file.write(data.to_yaml)
  end
end

def write_ramdisk_conf
  docker_service_d="/etc/systemd/system/docker.service.d"
  FileUtils.mkdir_p(docker_service_d) unless File.directory?(docker_service_d)
  ramdisk_conf = File.join(docker_service_d, "10-ramdisk.conf")
  File.open(ramdisk_conf, 'w') {|f| f.write("[Service]\nEnvironment=DOCKER_RAMDISK=true\n")}
  %x(systemctl daemon-reload)
  %x(systemctl restart docker)
end

# create build project
def create_build_project
  os_variant = {
    "openEuler-22.03-LTS-SP1" => "openEuler:22.03-LTS-SP1",
    "openEuler-22.03-LTS-SP2" => "openEuler:22.03-LTS-SP2",
    "openEuler-22.03-LTS-SP3" => "openEuler:22.03-LTS-SP3",
    "openEuler-22.03-LTS-Next" => "openEuler:22.03-lts-next-dailybuild",
    "openEuler-20.03-LTS-SP4" => "openEuler:20.03-LTS-SP4",
    "openEuler-24.03-LTS" => "openEuler:24.03-LTS",
    "master" => "openEuler:mainline",
  }

  puts "start create project ..."
  job_data = YAML.load_file("#{ENV['job']}")
  project_params = job_data['project_params']
  puts "job_data: #{job_data}"
  os_project = project_params['os_project']
  # os_variant
  branch = project_params['spec_branch']
  puts "branch: #{branch}"
  os_variant_val = os_variant[branch]
  puts "os_variant: #{os_variant_val}"
  project_params['build_targets'][0]['os_variant'] = YAML.dump(os_variant_val)
  # package_overrides
  event_data = YAML.load_file("#{ENV['event']}")
  puts "event_data: #{event_data}"
  pull_number = event_data['pull_number']
  package = project_params['package_overrides']
  package_dict['pr_id'] = pull_number.to_i
  package_overrides[package] = package_dict
  project_params['package_overrides']= YAML.dump(package_overrides)
  puts "project_params: #{project_params}"
  project_params_yaml = "/project_params.yaml"

  response=%x(#{CCB}/sbin/cli/ccb select projects os_project=#{os_project})
  response = JSON.parse(response)
  if response.length == 0
    File.open(project_params_yaml, 'w') do |f|
      f.write(YAML.dump(project_params))
    end

    response=%x(#{CCB}/sbin/cli/ccb upload-project-config --yaml #{project_params_yaml})
    response = JSON.parse(response)
    if response['code'] != 0
      puts "ccb upload-image-config error"
      pp response
      exit(99)
    end
  else
    response = {"data" => response[0]['_source']}
  end
  pp response
  json_file = "#{TMP_RESULT_ROOT}/eulermaker_create_project_result"
  write_build_json(response, json_file)
end

# update build project
def update_project
  job_data = YAML.load_file("#{ENV['job']}")
  project_params = job_data['project_params']
  os_project = job_data['project_params']['os_project']
  project_params.delete('os_project')
  project_params['build_env_macros'] = YAML.dump(project_params['build_env_macros'])
  project_params_yaml = "/project_params.yaml"
  File.open(project_params_yaml, 'w') do |f|
    f.write(YAML.dump(project_params))
  end

  response=%x(#{CCB}/sbin/cli/ccb update projects #{os_project} --yaml #{project_params_yaml})
  response = JSON.parse(response)
  if response['code'] != 0
    puts "ccb update project error"
    pp response
    exit(99)
  end

  pp response
  json_file = "#{TMP_RESULT_ROOT}/eulermaker_create_project_result"
  write_build_json(response, json_file)
end

# create image project
def create_image_project
  job_data = YAML.load_file("#{ENV['job']}")
  image_params = job_data['image_project_params']
  pipeline_name = image_params['pipeline_info']['pipeline_name']
  image_params_yaml = "/image_params.yaml"

  response=%x(#{CCB}/sbin/cli/ccb select pipeline pipeline_name=#{pipeline_name})
  response = JSON.parse(response)
  if response.length == 0
    File.open(image_params_yaml, 'w') do |f|
      f.write(YAML.dump(image_params))
    end
    response=%x(#{CCB}/sbin/cli/ccb upload-image-config --yaml #{image_params_yaml})
    response = JSON.parse(response)
    if response['code'] != 0
      puts "ccb upload-image-config error"
      pp response
      exit(99)
    end
  else
    response = {"data" => response[0]['_source']}
  end
  pp response
  json_file = "#{TMP_RESULT_ROOT}/eulermaker_create_image_result"
  write_build_json(response, json_file)
end

# start build project
def start_build_project
  build_type = ENV['build_type']
  rebuild_id = ENV['build_id']
  if rebuild_id
    rebuild_by_build_id(rebuild_id)
    return
  end

  if build_type == "single"
    build_single
  else
    build_non_single
  end
end

def rebuild_by_build_id(build_id)
  write_ramdisk_conf
  response=%x(#{CCB}/sbin/cli/ccb select jobs build_id=#{build_id})
  response = JSON.parse(response)
  job_id = response[0]["_id"]
  puts "start rebuild job: #{job_id}"
  system("#{CCB}/sbin/cli/ccb local-rebuild job_id=#{job_id} --showdocker")
rescue ex
  pp ex
  exit(99)
end

def build_non_single
  job_data = YAML.load_file("#{ENV['job']}")
  build_params = job_data['build_params']

  if build_params.nil?
    response=%x(#{CCB}/sbin/cli/ccb build os_project=#{ENV['project_name']} build_type=#{ENV['build_type']} arch=#{ENV['build_arch']})
  else
    build_params_yaml = "/build_params.yaml"
    File.open(build_params_yaml, 'w') do |f|
        f.write(YAML.dump(build_params))
    end
    response=%x(#{CCB}/sbin/cli/ccb build os_project=#{ENV['project_name']} build_type=#{ENV['build_type']} arch=#{ENV['build_arch']} --yaml #{build_params_yaml}) 
  end

  response = JSON.parse(response)
  if response['code'] != 0
    puts "ccb build os_project=#{ENV['project_name']} build_type=#{ENV['build_type']} arch=#{ENV['build_arch']} error"
    pp response
    exit(99)
  end

  build_id = response['data'].keys.first
  puts "os_project: #{ENV['project_name']}, build_type: #{ENV['build_type']} arch: #{ENV['build_arch']} start build, build_id: #{build_id}"

  return build_id
rescue ex
  pp ex
  exit(99)
end

# start build single
def build_single
  response=%x(#{CCB}/sbin/cli/ccb build-single os_project=#{ENV['project_name']} packages=#{ENV['package']})
  response = JSON.parse(response)
  if response['code'] != 0
    puts "ccb build-single os_project=#{ENV['project_name']} packages=#{ENV['package']} arch=#{ENV['build_arch']} error"
    pp response
    exit(99)
  end

  build_id = response['data'].keys.first
  puts "os_project: #{ENV['project_name']}, packages: #{ENV['package']} arch: #{ENV['build_arch']} start build, build_id: #{build_id}"

  return build_id
rescue ex
  pp ex
  exit(99)
end

# write reponse json to result root
def write_build_json(content, json_file)
  unless File.directory?(TMP_RESULT_ROOT)
    Dir.mkdir(TMP_RESULT_ROOT)
  end
  File.open(json_file, 'w') do |f|
    f.write(JSON.pretty_generate(content))
  end
end

# wait project finished
def loop_wait_build_project_finished(build_id)
  loop do
    response = %x(#{CCB}/sbin/cli/ccb select builds build_id=#{build_id})
    response = JSON.parse(response)[0]['_source']
    status = response['status']
    if [201, 202, 203].include?(status)
      puts "build_id: #{build_id} build finished, build_status: #{status}"
      pp response

      json_file = "#{TMP_RESULT_ROOT}/eulermaker_build_project_result"
      write_build_json(response, json_file)

      exit(99) unless status == 201
      break
    end

    puts "build_id: #{build_id} is building, build_status: #{status}"
    sleep(60)
  end
rescue ex
  pp ex
  exit(99)
end

# start build image
def start_build_image
  puts "start build image"
  response=%x(#{CCB}/sbin/cli/ccb build-image pipeline_id=#{ENV['pipeline_id']})
  response = JSON.parse(response)
  if response['code'] != 0
    puts "ccb build-image pipeline_id=#{ENV['pipeline_id']} error"
    pp response
    exit(99)
  end

  task_id = response['data']['id']
  puts "ccb build-image pipeline_id=#{ENV['pipeline_id']} start build, task_id=#{task_id}"

  return task_id
rescue ex
  pp ex
  exit(99)
end

# wait finished
def loop_wait_build_image_finished(task_id)
  loop do
    response = %x(#{CCB}/sbin/cli/ccb select image_task _id=#{task_id})
    response = JSON.parse(response)[0]['_source']
    status = response['status']
    if ['failed', 'success'].include?(status)
      puts "task_id: #{task_id} build image finished, build status: #{status}"
      pp response

      json_file = "#{TMP_RESULT_ROOT}/eulermaker_build_image_result"
      write_build_json(response, json_file)

      exit(99) unless status == 'success'
      break
    end

    puts "task_id: #{task_id} is building, build status: #{status}"
    sleep(60)
  end
rescue ex
  pp ex
  exit(99)
end
